﻿using MetaProperties.Core;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MetaProperties.Framework;

namespace MetaProperties.Core.Tests
{
    
    
    /// <summary>
    ///This is a test class for ObservableTest and is intended
    ///to contain all ObservableTest Unit Tests
    ///</summary>
    [TestClass()]
    public class ObservableTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        ///A test for Value
        ///</summary>
        public void ValueTestHelper<T>(T value)
        {
            Observable<T> target = new Observable<T>();
            T expected = default(T);
            T actual;
            actual = target.Value;
            Assert.AreEqual(expected, actual);

            expected = value;
            target.Value = expected;
            actual = target.Value;
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void ValueTest()
        {
            ValueTestHelper<GenericParameterHelper>(new GenericParameterHelper(5));
        }

        /// <summary>
        ///A test for Value
        ///</summary>
        public void MetaPropertyTestHelper<T>(T value)
        {
            Observable<T> target = new Observable<T>(value);
            T expected = value;
            IMetaProperty<T> metaProperty;
            metaProperty = target.MetaProperty;
            T actual = metaProperty.Value;
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void MetaPropertyTest()
        {
            MetaPropertyTestHelper<GenericParameterHelper>(new GenericParameterHelper(5));
        }

        /// <summary>
        ///A test for GetValue
        ///</summary>
        public void GetValueTest1Helper<T>()
        {
            Observable_Accessor<T> target = new Observable_Accessor<T>();
            object expected = default(T); 
            object actual;
            actual = target.GetValue();
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        public void GetValueTest1()
        {
            GetValueTest1Helper<GenericParameterHelper>();
        }

        /// <summary>
        ///A test for Observable`1 Constructor
        ///</summary>
        public void ObservableConstructorTest1Helper<T>()
        {
            Observable<T> target = new Observable<T>();
            T expected = default(T);
            T actual;
            target.Value = expected;
            actual = target.Value;
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void ObservableConstructorTest1()
        {
            ObservableConstructorTest1Helper<GenericParameterHelper>();
        }

        /// <summary>
        ///A test for Observable`1 Constructor
        ///</summary>
        public void ObservableConstructorTestHelper<T>(T value)
        {
            Observable<T> target = new Observable<T>(value);
            T expected = value;
            T actual;
            target.Value = expected;
            actual = target.Value;
            Assert.AreEqual(expected, actual);
        }

        [TestMethod()]
        public void ObservableConstructorTest()
        {
            ObservableConstructorTestHelper<GenericParameterHelper>(new GenericParameterHelper(1));
        }

        /// <summary>
        ///A test for UntypedValue
        ///</summary>
        [TestMethod()]
        public void UntypedValueTest()
        {
            GenericParameterHelper value = new GenericParameterHelper(5);
            UntypedObservable target = new Observable<GenericParameterHelper>(value);
            GenericParameterHelper expected = value;
            object actual;
            actual = target.UntypedValue;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for UntypedMetaProperty
        ///</summary>
        [TestMethod()]
        public void UntypedMetaPropertyTest()
        {
            GenericParameterHelper value = new GenericParameterHelper(5);
            UntypedObservable target = new Observable<GenericParameterHelper>(value);
            GenericParameterHelper expected = value;
            IMetaProperty actual;
            actual = target.UntypedMetaProperty;
            Assert.IsNotNull(actual);
            Assert.AreEqual(expected, actual.UntypedValue);
        }

        /// <summary>
        ///A test for GetValue
        ///</summary>
        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        public void GetValueTest()
        {
            GenericParameterHelper value = new GenericParameterHelper(5);
            UntypedObservable_Accessor target = new Observable_Accessor<GenericParameterHelper>(value);
            GenericParameterHelper expected = value;
            object actual;
            actual = target.GetValue();
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for GetMetaProperty
        ///</summary>
        [TestMethod()]
        [DeploymentItem("MetaProperties.Core.dll")]
        public void GetMetaPropertyTest()
        {
            GenericParameterHelper value = new GenericParameterHelper(5);
            UntypedObservable_Accessor target = new Observable_Accessor<GenericParameterHelper>(value);
            GenericParameterHelper expected = value;
            IMetaProperty actual;
            actual = target.GetMetaProperty();
            Assert.IsNotNull(actual);
            Assert.AreEqual(expected, actual.UntypedValue);
        }

        [TestMethod]
        public void ChangedEventsTest()
        {
            GenericParameterHelper value = new GenericParameterHelper(5);
            Observable<GenericParameterHelper> target = new Observable<GenericParameterHelper>();
            bool valueSetRaised = false;
            bool valueChangedRaised = false;
            bool propertyChangingRaised = false;
            bool propertyChangedRaised = false;
            bool untypedValueSetRaised = false;
            bool untypedValueChangedRaised = false;

            target.PropertyChanged += (s, e) =>
                {
                    Assert.AreEqual(target, s);
                    Assert.AreEqual("Value", e.PropertyName);
                    propertyChangedRaised = true;
                };

            target.PropertyChanging += (s, e) =>
            {
                Assert.AreEqual(target, s);
                Assert.AreEqual("Value", e.PropertyName);
                propertyChangingRaised = true;
            };

            target.ValueSet += (s, e) =>
            {
                Assert.AreEqual(target, s);
                Assert.AreEqual(default(GenericParameterHelper), e.OldValue);
                Assert.AreEqual(value, e.NewValue);
                valueSetRaised = true;
            };

            target.ValueChanged += (s, e) =>
            {
                Assert.AreEqual(target, s);
                Assert.AreEqual(default(GenericParameterHelper), e.OldValue);
                Assert.AreEqual(value, e.NewValue);
                valueChangedRaised = true;
            };

            target.UntypedValueChanged += (s, e) =>
            {
                Assert.AreEqual(target, s);
                untypedValueChangedRaised = true;
            };
            
            target.UntypedValueSet += (s, e) =>
            {
                Assert.AreEqual(target, s);
                untypedValueSetRaised = true;
            };

            target.Value = value;

            Assert.IsTrue(propertyChangingRaised);
            Assert.IsTrue(propertyChangedRaised);
            Assert.IsTrue(valueSetRaised);
            Assert.IsTrue(valueChangedRaised);
            Assert.IsTrue(untypedValueSetRaised);
            Assert.IsTrue(untypedValueChangedRaised);
        }


        [TestMethod]
        public void SetEventsTest()
        {
            GenericParameterHelper value = default(GenericParameterHelper);
            Observable<GenericParameterHelper> target = new Observable<GenericParameterHelper>();
            bool valueSetRaised = false;
            bool valueChangedRaised = false;
            bool propertyChangingRaised = false;
            bool propertyChangedRaised = false;
            bool untypedValueSetRaised = false;
            bool untypedValueChangedRaised = false;

            target.PropertyChanged += (s, e) =>
            {
                propertyChangedRaised = true;
            };

            target.PropertyChanging += (s, e) =>
            {
                propertyChangingRaised = true;
            };

            target.ValueSet += (s, e) =>
            {
                Assert.AreEqual(target, s);
                Assert.AreEqual(default(GenericParameterHelper), e.OldValue);
                Assert.AreEqual(value, e.NewValue);
                valueSetRaised = true;
            };

            target.ValueChanged += (s, e) =>
            {
                valueChangedRaised = true;
            };

            target.UntypedValueChanged += (s, e) =>
            {
                untypedValueChangedRaised = true;
            };

            target.UntypedValueSet += (s, e) =>
            {
                Assert.AreEqual(target, s);
                untypedValueSetRaised = true;
            };

            target.Value = value;

            Assert.IsFalse(propertyChangingRaised);
            Assert.IsFalse(propertyChangedRaised);
            Assert.IsTrue(valueSetRaised);
            Assert.IsFalse(valueChangedRaised);
            Assert.IsTrue(untypedValueSetRaised);
            Assert.IsFalse(untypedValueChangedRaised);
        }
    }
}
